package com.atguigu.zk.util;

import com.atguigu.constant.CommonConstantValue;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;

/**
 * @ClassName ZkUtil
 * @DeScription ZkUtil
 * @Author 剧情再美终是戏
 * @Date 2019/11/22 19:25
 * @Version 1.0
 **/
public class ZkUtil {

    private static Logger logger = Logger.getLogger(ZkUtil.class);

    private ZkUtil() {
    }


    // zk重试的策略
    private static ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3, Integer.MAX_VALUE);


    /**
     * 获取zk连接
     *
     * @param connectString zk连接地址
     * @param namespace     获取连接的初始化根目录
     * @return org.apache.curator.framework.CuratorFramework
     * @Author 剧情再美终是戏
     * @Date 2019/11/22
     * @Version 1.0
     **/
    public static CuratorFramework getConnection(String connectString, String namespace) {
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString(connectString)
                .sessionTimeoutMs(CommonConstantValue.ZK_SESSIONTIMEOUTMS)
                .connectionTimeoutMs(CommonConstantValue.ZK_CONNECTIONTIMEOUTMS)
                .namespace(namespace)
                .retryPolicy(retryPolicy)
                .build();
        curatorFramework.start();
        return curatorFramework;
    }

    /**
     * 创建节点,支持递归创建节点， 默认使用ZooDefs.Ids.OPEN_ACL_UNSAFE权限(开放权限)
     *
     * @param curatorFramework Zookeeper连接操作对象
     * @param path             创建节点的路径
     * @param data             创建节点的数据
     * @param createMode       节点类型，详情见CreateMode这个枚举类
     * @return void
     * @Author 剧情再美终是戏
     * @Date 2019/11/22
     * @Version 1.0
     **/
    public static void create(CuratorFramework curatorFramework, String path, byte[] data, CreateMode createMode) throws Exception {
        if (null == curatorFramework) {
            logger.error("CuratorFramework 实例为空!");
            return;
        }
        curatorFramework.create().creatingParentsIfNeeded()//递归创建,如果没有父节点,自动创建父节点
                .withMode(createMode)
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)//设置ACL,和原生API相同
                .forPath(path, data);
    }

    /**
     * 获取指定路径下的数据
     *
     * @param curatorFramework Zookeeper连接操作对象
     * @param path             查询数据的路径
     * @param nodeStat         获取stat信息存储到stat对象
     * @return byte[]
     * @Author 剧情再美终是戏
     * @Date 2019/11/22
     * @Version 1.0
     **/
    public static byte[] getData(CuratorFramework curatorFramework, String path, Stat nodeStat) throws Exception {
        if (null == curatorFramework) {
            logger.error("CuratorFramework 实例为空!");
            return null;
        }
        return curatorFramework.getData()
                .storingStatIn(nodeStat)
                .forPath(path);
    }

    /**
     * 获取指定路径下的数据
     *
     * @param curatorFramework Zookeeper连接操作对象
     * @param path             查询数据的路径
     * @param watcher          查询后的监听器，如果数据有被修改，可以被触发
     * @return byte[]
     * @Author 剧情再美终是戏
     * @Date 2019/11/22
     * @Version 1.0
     **/
    public static byte[] getData(CuratorFramework curatorFramework, String path, Watcher watcher) throws Exception {
        if (null == curatorFramework) {
            logger.error("CuratorFramework 实例为空!");
            return null;
        }
        return curatorFramework.getData()
                .usingWatcher(watcher)
                .forPath(path);
    }


    /**
     * 修改数据
     *
     * @param curatorFramework Zookeeper连接操作对象
     * @param path             修改数据的路径
     * @param data             数据
     * @return org.apache.zookeeper.data.Stat
     * @Author 剧情再美终是戏
     * @Date 2019/11/22
     * @Version 1.0
     **/
    public static Stat setData(CuratorFramework curatorFramework, String path, byte[] data) throws Exception {
        if (null == curatorFramework) {
            logger.error("CuratorFramework 实例为空!");
            return null;
        }
        return curatorFramework.setData()
                .withVersion(-1)
                .forPath(path, data);

    }

    /**
     * 删除指定路径的节点
     *
     * @param curatorFramework Zookeeper连接操作对象
     * @param path             删除数据的指定路径
     * @return void
     * @Author 剧情再美终是戏
     * @Date 2019/11/22
     * @Version 1.0
     **/
    public static void delete(CuratorFramework curatorFramework, String path) throws Exception {
        if (null == curatorFramework) {
            logger.error("CuratorFramework 实例为空!");
            return;
        }
        curatorFramework.delete()
                .deletingChildrenIfNeeded()
                .forPath(path);
    }

    /**
     * 关闭资源
     *
     * @param curatorFramework Zookeeper连接操作对象
     * @return void
     * @Author 剧情再美终是戏
     * @Date 2019/11/22
     * @Version 1.0
     **/
    public static void close(CuratorFramework curatorFramework) {
        if (null == curatorFramework) {
            logger.error("CuratorFramework 实例为空!");
            return;
        }
        curatorFramework.close();
    }
}
